use crate::config::config::Config;
use csv::{Writer, WriterBuilder};
use regex::Regex;
use serde_json::{from_str, Value};
use std::error::Error;
use std::path::{Path, PathBuf};
use std::{env, fs};
use tokio::fs::File;
use tokio::io::AsyncReadExt;
use tokio::sync::mpsc;
use tokio::task;

pub async fn resolve(config: &Config) -> Result<(), Box<dyn Error>> {
    // 验证路径是否合法
    if let Ok(_) = check_file(config) {
        // 根据路径类型调用不同的处理逻辑
        if config.path.is_file() {
            handle_file(config.path.clone(), config).await?;
        } else if config.path.is_dir() {
            handle_directory(config.path.clone(), config).await?;
        } else {
            return Err(
                format!("Path is neither a file nor a directory:  {:?}", config.path).into(),
            );
        }
    } else {
        return Err(format!("Path is neither a file nor a directory: {:?}", config.path).into());
    }
    Ok(())
}

fn check_file(config: &Config) -> Result<(), Box<dyn Error>> {
    // 检查路径是否存在
    if !config.path.exists() {
        return Err(format!("Path does not exist: {:?}", config.path).into());
    }
    Ok(())
}

fn extract_message(log_line: &str) -> Option<String> {
    // 构建正则表达式
    let re = Regex::new(r".*\^\|\^(.*)$").unwrap();

    // 匹配并提取 %msg 部分
    re.captures(log_line)
        .and_then(|caps| caps.get(1).map(|m| m.as_str().to_string()))
}

fn extract_json_field(json_str: &str, field_name: &str) -> Option<Value> {
    // 解析 JSON 字符串
    match from_str::<Value>(json_str) {
        Ok(json_value) => {
            // 提取指定字段
            json_value.get(field_name).cloned()
        }
        Err(_) => None,
    }
}

async fn handle_file(path: PathBuf, config: &Config) -> Result<(), Box<dyn Error>> {
    let mut file = File::open(path.clone()).await?;
    // 创建缓冲区
    let mut contents = String::new();
    file.read_to_string(&mut contents).await?;
    // 创建 CSV 文件
    let file = create_file(&*path, "csv").await?;
    // 使用 WriterBuilder 配置 Writer
    let mut wtr = WriterBuilder::new()
        .quote_style(csv::QuoteStyle::Never) // 设置引号风格
        .from_writer(file);

    // 写入表头
    wtr.write_record(&[
        "编号",
        "当前毫秒级时间戳",
        "帧号",
        "经度",
        "纬度",
        "航向角",
        "速度（km/h）",
        "加速度",
    ])?;

    let mut count = 0;
    // 按行处理内容
    for (_i, line) in contents.lines().enumerate() {
        if let Some(message) = extract_message(line) {
            if let Some(field_value) = extract_json_field(&message, "participantTrajectories")
                .and_then(|v| v.as_array().cloned())
            {
                json_to_csv(field_value, config, &mut wtr)?;
                count += 1;
            }
        } else {
            eprintln!("No match found in line: {}", line);
        }
    }
    println!("{} lines processed.", count);

    Ok(())
}

fn json_to_csv(
    array: Vec<Value>,
    config: &Config,
    wtr: &mut Writer<fs::File>,
) -> Result<(), Box<dyn Error>> {
    for item in array {
        match &config.id {
            Some(id_value) => {
                if let Some(value_array) = item.get("value").and_then(|v| v.as_array()) {
                    for item in value_array {
                        if let Some(id_item) = item.get("id").and_then(|v| match v {
                            Value::String(s) => Some(s.to_string()),
                            Value::Number(n) => n.to_string().into(),
                            _ => None,
                        }) {
                            if id_item == *id_value {
                                get_result(item, wtr)?
                            }
                        }
                    }
                }
            }
            None => {
                if let Some(role) = item.get("role").and_then(|r| r.as_str()) {
                    if config.role.as_str() == role {
                        if let Some(value_array) = item.get("value").and_then(|v| v.as_array()) {
                            for item in value_array {
                                get_result(item, wtr)?
                            }
                        }
                    }
                }
            }
        }
    }
    Ok(())
}

fn get_result(item: &Value, wtr: &mut Writer<fs::File>) -> Result<(), Box<dyn Error>> {
    let id = item
        .get("id")
        .map(|v| v.to_string())
        .unwrap_or("".to_string())
        .to_string();
    let global_time_stamp = item
        .get("globalTimeStamp")
        .and_then(|v| match v {
            Value::String(s) => Some(s.to_string()),
            Value::Number(n) => n.to_string().into(),
            _ => None,
        })
        .unwrap_or_else(|| "".to_string());
    let frame_id = item
        .get("frameId")
        .map(|v| v.to_string())
        .unwrap_or("".to_string())
        .to_string();
    let longitude = item
        .get("longitude")
        .map(|v| v.to_string())
        .unwrap_or("".to_string())
        .to_string();
    let latitude = item
        .get("latitude")
        .map(|v| v.to_string())
        .unwrap_or("".to_string())
        .to_string();
    let course_angle = item
        .get("courseAngle")
        .map(|v| v.to_string())
        .unwrap_or("".to_string())
        .to_string();
    let speed = item
        .get("speed")
        .map(|v| v.to_string())
        .unwrap_or("".to_string())
        .to_string();
    let acc = item
        .get("acc")
        .map(|v| v.to_string())
        .unwrap_or("".to_string())
        .to_string();

    wtr.write_record(&[
        id,
        global_time_stamp,
        frame_id,
        longitude,
        latitude,
        course_angle,
        speed,
        acc,
    ])?;

    Ok(())
}

async fn handle_directory(path: PathBuf, config: &Config) -> Result<(), Box<dyn Error>> {
    // 获取程序路径
    let program_path = env::current_exe()?.canonicalize()?;

    // 创建一个通道来收集所有的异步任务
    let (tx, mut rx) = mpsc::channel(100);
    for entry in fs::read_dir(path)? {
        let entry = entry?;
        let entry_path = entry.path();

        // 获取 entry_path 的全路径
        let full_entry_path = entry_path.canonicalize()?;
        // 排除程序自己
        if full_entry_path == program_path {
            continue;
        }

        if entry_path.is_dir() {
            Box::pin(handle_directory(entry_path, &config)).await?;
        } else {
            // 发送异步任务到通道
            let tx_clone = tx.clone();
            let config_clone = config.clone();
            task::spawn(async move {
                if let Err(err) = handle_file(entry_path, &config_clone).await {
                    eprintln!("Error processing file: {}", err);
                }
                if let Err(err) = tx_clone.send(()).await {
                    // 通道关闭，任务已完成
                    eprintln!("Error sending completion signal: {}", err);
                }
            });
        }
    }
    // 关闭发送端
    drop(tx);
    // 等待所有任务完成
    while let Some(_) = rx.recv().await {}
    Ok(())
}

async fn create_file(path: &Path, suffix: &str) -> Result<fs::File, Box<dyn Error>> {
    let mut new_path = PathBuf::from(path);
    new_path.set_extension(suffix);
    // 检查路径是否有效
    if !new_path.exists() && !new_path.parent().map_or(true, |p| p.exists()) {
        return Err(format!("父目录不存在: {}", new_path.display()).into());
    }
    // 创建文件
    let file = fs::File::create(&new_path)?;
    Ok(file)
}
